Crate zebra_network

source ·
Expand description

Networking code for Zebra.

§Network Protocol Design

The Zcash network protocol is inherited from Bitcoin, which uses a stateful network protocol in which messages can arrive in any order (even before a handshake is complete!). The same Bitcoin message may be a request or a response depending on context.

§Achieving Concurrency

This crate translates the legacy Zcash network protocol into a stateless, request-response oriented protocol defined by the Request and Response enums. zebra-network completely encapsulates all peer handling code behind a single tower::Service representing “the network”, which load-balances outbound Requests over available peers.

Unlike the underlying legacy network protocol, Zebra’s PeerSet tower::Service guarantees that each Request future will resolve to the correct Response, rather than an unrelated Response message.

Each peer connection is handled by a distinct [peer::Connection] task. The Zcash network protocol is bidirectional, so Zebra interprets incoming Zcash messages as either:

All connection state is isolated to individual peers, so this design is structurally immune to the recent ping attack.

§Connection Pool

Because tower::Services provide backpressure information, we can dynamically manage the size of the connection pool according to inbound and outbound demand. The inbound service can shed load when it is not ready for requests, causing those peer connections to close, and the outbound service can connect to additional peers when it is overloaded.

§zebra-network Structure

[zebra-network::init] is the main entry point for zebra-network. It uses the following services, tasks, and endpoints:

§Low-Level Network Connections

Inbound Zcash Listener Task:

  • accepts inbound connections on the listener port
  • initiates Zcash [peer::Handshake]s, which creates [peer::Connection] tasks for each inbound connection

Outbound Zcash Connector Service:

  • initiates outbound connections to peer addresses
  • initiates Zcash [peer::Handshake]s, which creates [peer::Connection] tasks for each outbound connection

Zebra uses direct TCP connections to share blocks and mempool transactions with other peers.

The [isolated] APIs provide anonymised TCP and Tor connections to individual peers. These isolated connections can be used to send user-generated transactions anonymously. Tor connections are currently disabled until arti-client’s dependency x25519-dalek v1.2.0 is updated to a higher version. See #5492.

§Individual Peer Connections

Each new peer connection spawns the following tasks:

peer::Client Service:

  • provides an interface for outbound requests to an individual peer
    • accepts Requests assigned to this peer by the PeerSet
    • sends each request to the peer as Zcash Message
    • waits for the inbound response Message from the peer, and returns it as a Response

[peer::Connection] Service:

  • manages connection state: awaiting a request, or handling an inbound or outbound response
  • provides an interface for inbound requests from an individual peer
    • accepts inbound Zcash Messages from this peer
    • handles each message as a Request to the inbound service
    • sends the Response to the peer as Zcash Messages
  • drops peer connections if the inbound request queue is overloaded

Since the Zcash network protocol is bidirectional, inbound and outbound connections are handled using the same logic.

§Connection Pool

PeerSet Network Service:

  • provides an interface for other services and tasks running within this node to make requests to remote peers (“the rest of the network”)

Inbound Network Service:

  • provides an interface for remote peers to request data held by this node
    • accepts inbound Zcash Requests from [peer::Connection]s
    • handles each message as a Request to the local node
    • sends the Response to the [peer::Connection]

Note: the inbound service is implemented by the [zebra-network::init] caller.

Peer Inventory Service:

  • tracks gossiped inv advertisements for each peer
  • updated before each PeerSet request is processed
  • tracks missing inventory for each peer
  • used by the PeerSet to route block and transaction requests to peers that have the requested data

§Peer Discovery

AddressBook Service:

  • maintains a list of peer addresses and associated connection attempt metadata
  • address book metadata is used to prioritise peer connection attempts
  • updated by an independent thread based on peer connection status changes
  • caches peer addresses to disk regularly using an independent task

Initial Seed Peer Task: On startup:

  • loads seed peers from the config, resolving them via DNS if required
  • loads cached peer addresses from disk
  • initiates new outbound peer connections to seed and cached peers
  • adds seed and cached peer addresses to the AddressBook

Peer Crawler Task:

  • discovers new peer addresses by sending Addr requests to connected peers
  • initiates new outbound peer connections in response to application demand

Re-exports§

Modules§

Structs§

  • A database of peer listener addresses, their advertised services, and information on when they were last seen.
  • The “client” duplex half of a peer connection.
  • The metadata for a peer connection.
  • A thin wrapper for SocketAddr which hides peer IP addresses in logs and metrics.
  • A very basic retry policy with a limited number of retry attempts.
  • A wrapper around Arc<PeerError> that implements Error.
  • A protocol version number.
  • A version message.

Enums§

  • The peer address that we are handshaking with.
  • An error during a handshake with a remote peer.
  • A generic peer inventory response status.
  • Peer connection state, based on our interactions with the peer.
  • An error related to peer connection handling.
  • A network request, represented in internal format.
  • A response to a network request, represented in internal format.

Constants§

Functions§

  • Creates a Zcash peer connection using the provided data stream. This connection is completely isolated from all other node state.
  • Creates a direct TCP Zcash peer connection to addr. This connection is completely isolated from all other node state.
  • Initialize a peer set, using a network config, inbound_service, and latest_chain_tip.

Type Aliases§

  • Type alias to make working with tower traits easier.